# -*- coding: latin-1 -*-
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation; either version 3, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY
# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.

"Module to enhance python diversity for non-English speakers, begginers et. al."

__author__ = "Mariano Reingart (reingart@gmail.com)"
__copyright__ = "Copyright (C) 2012 Mariano Reingart"
__license__ = "LGPL 3.0"


import re

# original messages to be translated:
# (note that newlines are striped from extracted messages in source code)
msgid = [
    "Traceback (most recent call last):",
    "  File \"%.500s\", line %d, in %.500s",
    "invalid syntax",
    "integer division or modulo by zero",
    "name '%.200s' is not defined",
    ]

# translated messages (in Spanish as this is a proof-of-concept)
# (note that placeholders should be modified to use %s only right now)
msgstr = [
    "Traza de rastreo (llamada mas reciente ultima):",
    "  Archivo \"%s\", linea %s, en %s",
    "sintaxis invalida",
    "division entera o modulo por cero",
    "nombre '%s' no esta definido",
    ]


# The pattern matching code is based on Graham Horler recipe (PSF license)
# http://code.activestate.com/recipes/534139-enhanced-safe-string-formatting/

safmt_pat = re.compile(r'''
    %                     # Start with percent,
    (?:\( ([^()]*) \))?   # optional name in parens (do not capture parens),
    [-+ #0]*              # zero or more flags
    (?:\*|[0-9]*)         # optional minimum field width
    (?:\.(?:\*|[0-9]*))?  # optional dot and length modifier
    [EGXcdefgiorsux%]     # type code (or [formatted] percent character)
    ''', re.VERBOSE)


def format_to_re(template):
    r"""Convert String Formatting Operations (%) to Regular Expressions (re)
    
    >>> format_to_re('  File "%.500s", line %d, in %.500s')
    '\\ \\ File\\ \\"(.*)\\"\\,\\ line\\ (.*)\\,\\ in\\ (.*)'
    >>> format_to_re("name '%.200s' is not defined")
    "name\\ \\'(.*)\\'\\ is\\ not\\ defined"
    """

    ret = []
    last = i = 0
    d = {}
    di = 0
    pat = safmt_pat
    
    while 1:
        mo = pat.search(template, i)
        
        if not mo:
            # End of string
            text = template[last:]
            ret.append(re.escape(text))
            break
        
        i = mo.end(0)
        
        stanza, name = mo.group(0, 1)
        if stanza[-1] == "%":
            # No argument is converted, results in a "%" character in the result.
            dat = re.escape(stanza)
        else:
            fmt = ".*" # TODO!
        
        if name is not None:
            dat = "(?P<%s>%s)" % (name, fmt)
        else:
            ##numargs += mo.group(0).count("*")            
            dat = "(%s)" % (fmt) 
        
        text = template[last:mo.start()]
        ret.append(re.escape(text))
        ret.append(dat)
        last = i
    
    return ''.join(ret)


# create regular expresions and compile all messages 
msgre = [re.compile(format_to_re(msg)) for msg in msgid]


def i18n(msg):
    r"""Translate a message, detecting placeholders and preserving their values
    
    >>> i18n('Traceback (most recent call last):')
    'Traza de rastreo (llamada mas reciente ultima):'
    >>> i18n('  File "<stdin saraza>", line 1, in <module>')
    '  Archivo "<stdin saraza>", linea 1, en <module>'
    """
    # iterate over al the regex expresions for original messages:
    for i, regex in enumerate(msgre):
        match = regex.match(msg)
        if match:
            # find the desired translation
            translation = msgstr[i]     # TODO: dict lookup according locale
            if match.groups():
                # replace placeholders with extracted argument values
                return translation % match.groups()
            else:
                return translation
    return None


def i18n_traceback(language=None):
    """Provide an internationalized translation of a given tracebak:
    Examples (not implemented currently):
    >>> 1/0
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ZeroDivisionError: integer division or modulo by zero
    >>> ##from __diversity__ import i18n_traceback
    >>> i18n_traceback('es_AR')
    >>> 1/0
    Traza de rastreo (llamada mas reciente ultima):
      Archivo "<stdin>", linea 1, en <module>
    ZeroDivisionError: division entera o modulo por cero
    >>> i18n_traceback('C')
    >>> 1/0
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    ZeroDivisionError: integer division or modulo by zero    
    """

        

if __name__ == "__main__":
    for msg in msgid:
        print ">>> format_to_re(%s)" % repr(msg)
        print repr(format_to_re(msg))
    
    tb = """Traceback (most recent call last):
  File "<stdin saraza>", line 1, in <module>"""
    print "translating..."
    for line in tb.split("\n"):
        print ">>> i18n(%s)" % repr(line)
        print repr(i18n(line))
